package TAIC.Classifier;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.PrintStream;
import java.util.Scanner;

import weka.classifiers.functions.Logistic;
import weka.core.Instances;
import weka.core.Instance;
import TAIC.test.TestMode;

public class LogisticRegression extends Classifier {
	public static int MaxClass = TestMode.para.getParaInt( "MaxClass" ) ;
	public static int DIM = 800 ; 
	
	public boolean pipe = true ;
	Logistic logistic ; 
	Instances corpus = null ; 
	
	@Override
	public boolean isPipe() {
		return pipe ; 
	}
	
	@Override
	public double test(String testFile) {
		int all = 0 ;
		int correct = 0 ; 
		try {
			Scanner scanner ;
			if ( ! isPipe() )  scanner = new Scanner ( new File ( testFile ) ) ;
			else scanner = new Scanner ( new ByteArrayInputStream( testPipe ) ) ;
			double x[] = new double [ DIM + 1 ] ;

			int classNo ;
			while ( scanner.hasNext() ) {
				classNo = Integer.valueOf( scanner.next());
				x[ 0 ] = 1 - classNo ;
				for ( int i = 1 ; i <= DIM; i ++ ) x[ i ] = 0 ; 
				String buff = scanner.nextLine() ;
				Scanner buffScanner = new Scanner ( buff ); 
				while ( buffScanner.hasNext() ) {
					String str = buffScanner.next() ;
					int pos = str.indexOf( ':' ); 
					int index = Integer.valueOf( str.substring(0, pos) );
					int num = Integer.valueOf( str.substring(pos +1 ) );
					x [ index ] = num ; 
				}
				buffScanner.close() ;
				Instance ins = new Instance ( 1.0, x );
				ins.setDataset( corpus ); 
				if ( classNo == (int)logistic.classifyInstance(ins )) correct ++ ;
				//System.out.println ( classNo + " " + (int)logistic.classifyInstance(ins ) ) ; 
				all ++ ;
			}
		}catch ( Exception e) { 
			e.printStackTrace() ;
		}
	//	System.exit (0 ); 
		return correct/ (double)all ; 
	}

	@Override
	public void train(String trainFile) {
		logistic = new Logistic ( ) ;
		int [] x = new int [ DIM ];
		try {
			PrintStream fout = new PrintStream ( new File ( "train_logit.arff" ) ) ;
			fout.println("@relation InstanceResultListener") ; 
			fout.print( "@attribute class {" ) ;
			for ( int i = 0 ; i < MaxClass - 1 ; i ++ ) fout.print ( (i+1) + "," ) ;
			fout.println ( MaxClass + "}" ) ; 
			for ( int i = 0 ; i < DIM ; i ++ ) fout.println ( "@attribute x" + i + " real" ) ;

			fout.println ( "@data" );
			Scanner scanner ;
			if ( ! isPipe() )  scanner = new Scanner ( new File ( trainFile ) ) ;
			else scanner = new Scanner ( new ByteArrayInputStream( trainPipe ) ) ;
			
			for ( int i = 0 ; i < DIM ; i ++ ) x [ i ] = 0 ;
			while ( scanner.hasNext() ) {
				int classNo = translateClass( scanner.next());
				fout.print( classNo ) ;
				String buff = scanner.nextLine() ;
				Scanner buffScanner = new Scanner ( buff ); 
				while ( buffScanner.hasNext() ) {
					String str = buffScanner.next() ;
					int pos = str.indexOf( ':' ); 
					int index = Integer.valueOf( str.substring(0, pos) );
					int num = Integer.valueOf( str.substring(pos +1 ) );
					x [ index - 1 ] = num ; 
				}
				for ( int i = 0 ; i < DIM ; i ++ ) fout.print(  "," + x[ i ] ) ;
				buffScanner.close() ;
				fout.println(); 
			}
			
			fout.close() ; 
			corpus = new Instances ( new FileReader ( "train_logit.arff" )) ;
			corpus.setClass( corpus.attribute("class")) ;
			//logistic.setMaxIts( 40 ) ;
			//logistic.setDebug( true );
			logistic.buildClassifier( corpus ) ;
		}catch ( Exception e) { 
			e.printStackTrace() ;
		}
	}

	public int translateClass ( String str) {
		return Integer.valueOf( str ) + 1  ;  
	}
	
}
